//public class Interface{
//    public static void main(String[] args){
//        System.out.println("Interface");
//    }
//
//    /**
//     * 接口与继承 接口
//     */
//    void Interface() {
//        /**
//         * 物理攻击接口
//         */
//        // 创建一个接口 File->New->Interface AD ，声明一个方法 physicAttack 物理攻击，但是没有方法体，是一个“空”方法
//        public interface AD {
//            //物理伤害
//            public void physicAttack();
//        }
//
//        /**
//         * 设计一类英雄，能够使用物理攻击
//         */
//        // 继承了Hero 类，所以继承了name,hp,armor等属性
//        public class ADHero extends Heros implements AD{
//            // 实现某个接口，就相当于承诺了某种约定
//            // 所以，实现了AD这个接口，就必须提供AD接口中声明的方法physicAttack()
//            // 实现在语法上使用关键字 implements
//            @Override
//            public void physicAttack() {
//                System.out.println("进行物理攻击");
//            }
//        }
//
//        /**
//         * 魔法攻击接口
//         */
//        // 创建一个接口 File->New->Interface AP ，声明一个方法 magicAttack 魔法攻击，但是没有方法体，是一个“空”方法
//        public interface AP {
//            public void magicAttack();
//        }
//
//        /**
//         * 设计一类英雄，只能使用魔法攻击
//         */
//        public class APHero extends Heros implements AP{
//            // 实现了AP这个接口，就必须提供AP接口中声明的方法magicAttack()
//            // 实现在语法上使用关键字 implements
//            @Override
//            public void magicAttack() {
//                System.out.println("进行魔法攻击");
//            }
//        }
//
//
//        /**
//         * 设计一类英雄，既能进行物理攻击，又能进行魔法攻击
//         */
//        //同时能进行物理和魔法伤害的英雄
//        public class ADAPHero extends Heros implements AD,AP{
//            @Override
//            public void magicAttack() {
//                System.out.println("进行魔法攻击");
//            }
//
//            @Override
//            public void physicAttack() {
//                System.out.println("进行物理攻击");
//            }
//        }
//
//
//        /**
//         * 什么样的情况下该使用接口?
//         */
//        // 学习一个知识点，是由浅入深得进行的。 这里呢，只是引入了接口的概念，要真正理解接口的好处，需要更多的实践，以及在较为复杂的系统中进行大量运用之后，才能够真正理解，比如在学习了多态之后就能进一步加深理解。
//        // 刚刚接触一个概念，就希望达到炉火纯青的学习效果，这样的学习目标是不科学的
//    }
//
//
//    /**
//     * 接口与继承 对象转型
//     */
//    void ObjectTransformation() {
//        /**
//         * 明确引用类型与对象类型的概念
//         */
//        public class Hero {
//            // 此例子里，有一个对象 new ADHero(), 同时也有一个引用ad
//            // 对象是有类型的， 是ADHero
//            // 引用也是有类型的，是ADHero
//            // 通常情况下，引用类型和对象类型是一样的
//            // 所谓的转型，是指当引用类型和对象类型不一致的时候，才需要进行类型转换
//            ADHero ad = new ADHero();
//            Hero h = new Hero();
//            Support s =new Support();
//
//            /**
//             * 子类转父类(向上转型)
//             */
//            // 类型转换指的是把一个引用所指向的对象的类型，转换为另一个引用的类型
//            // 如何判断到底能否转换成功？
//            // 简单的做法，就是把右边的当做左边来用，看说得通不
//            //
//            // 右边ad引用所指向的对象的类型是 物理攻击英雄
//            // 左边h引用的类型是 普通英雄
//            // 把物理攻击英雄 当做 普通英雄，说不说得通？ 说得通，就可以转
//            // 所有的子类转换为父类，都是说得通的.
//            h = ad;
//
//
//            /**
//             * 父类转子类(向下转型)
//             */
//            // 父类转子类，有的时候行，有的时候不行，所以必须进行强制转换。
//            // 强制转换的意思就是 转换有风险，风险自担。
//
//            h = ad; // 把ad当做Hero使用，一定可以，转换之后，h引用指向一个ad对象
//            ad = (ADHero) h; // h引用有可能指向一个ad对象，也有可能指向一个support对象，所以把h引用转换成AD类型的时候，就有可能成功，有可能失败，因此要进行强制转换，到底能不能转换成功，要看引用h到底指向的是哪种对象。
//            h = s; // 把一个support对象当做Hero使用，一定可以，转换之后，h引用指向一个support对象
//            ad = (ADHero)h; // 这个时候，h指向的是一个support对象，所以转换成ADHero类型，会失败。
//            // 失败的表现形式是抛出异常 ClassCastException 类型转换异常.
//
//
//            /**
//             * 没有继承关系的两个类，互相转换
//             */
//            // 没有继承关系的两个类，互相转换，一定会失败
//            // 虽然 ADHero 和 APHero 都继承了Hero，但是彼此没有互相继承关系
//            // "把魔法英雄当做物理英雄来用",在语义上也是说不通的
//            APHero ap = new APHero();
//            ad = (ADHero) ap; // 没有继承关系的类型进行互相转换一定会失败，所以会出现编译错误
//
//
//            /**
//             * 实现类转换成接口(向上转型)
//             */
//            // 引用ad 指向的对象是ADHero类型，这个类型实现了AD接口
//            // 此处，把一个ADHero类型转换为AD接口
//            // 从语义上来讲，把一个ADHero当做AD来使用，而AD接口只有一个physicAttack方法，这就意味着转换后就有可能要调用physicAttack方法，而ADHero一定是有physicAttack方法的，所以转换是能成功的。
//            AD adi = ad;
//
//
//            /**
//             * 接口转换成实现类(向下转型)
//             */
//            AD ad1 = ad; // ad引用指向ADHero， 而ad1引用是接口类型：AD，实现类转换为接口，是向上转型，所以无需强制转换，并且一定能成功
//            ADHero adHero = (ADHero) ad1; // ad1 实际上是指向一个ADHero的，所以能够转换成功
//            ADAPHero adapHero = (ADAPHero) ad1; // ad1引用 所指向的对象是一个ADHero，要转换为ADAPHero就会失败。
//            adapHero.magicAttack(); // 假设能够转换成功，那么就可以使用magicAttack方法，而adi引用所指向的对象ADHero是没有magicAttack方法的。
//
//
//            /**
//             * instanceof
//             */
//            // instanceof Hero 判断一个引用所指向的对象，是否是Hero类型，或者Hero的子类
//            Hero h1 = ad;
//            Hero h2 = ap;
//            //判断引用h1指向的对象，是否是ADHero类型
//            System.out.println(h1 instanceof ADHero);
//
//            //判断引用h2指向的对象，是否是APHero类型
//            System.out.println(h2 instanceof APHero);
//
//            //判断引用h1指向的对象，是否是Hero的子类型
//            System.out.println(h1 instanceof Hero);
//        }
//    }
//
//
//    /**
//     * 接口与继承 重写
//     */
//    void Rewrite() {
//        // 子类可以继承父类的对象方法
//        // 在继承后，重复提供该方法，就叫做方法的重写
//        // 又叫覆盖 override
//
//        /**
//         * 父类 Item
//         */
//        public class Item {
//            String name;
//            int price;
//            public void buy(){
//                System.out.println("购买");
//            }
//            public void effect() {
//                System.out.println("物品使用后，可以有效果");
//            }
//        }
//
//        /**
//         * 子类 LifePotion
//         */
//        public class LifePotion extends Item{
//            // 子类LifePotion 继承 Item，同时也提供了方法 effect
//            public void effect(){
//                System.out.println("血瓶使用后，可以回血");
//            }
//        }
//
//        /**
//         * 调用重写的方法
//         */
//        void main1() {
//            Item i = new Item();
//            i.effect();
//            // 调用就会执行重写的方法，而不是从父类的方法
//            // 所以 LifePotion 的effect会打印： "血瓶使用后，可以回血"
//            LifePotion lp =new LifePotion();
//            lp.effect();
//        }
//
//
//        /**
//         * 如果没有重写这样的机制怎么样？
//         */
//        // 如果没有重写这样的机制，也就是说LifePotion这个类，一旦继承了Item，所有方法都不能修改了。
//        // 但是LifePotion又希望提供一点不同的功能，为了达到这个目的，只能放弃继承Item,重新编写所有的属性和方法，然后在编写effect的时候，做一点小改动.
//        // 这样就增加了开发时间和维护成本
//    }
//
//
//    /**
//     * 接口与继承 多态
//     */
//    void Polymorphism() {
//        /**
//         * 操作符的多态
//         */
//        // 同一个操作符在不同情境下，具备不同的作用
//        int i = 5;
//        int j = 6;
//        int k = i+j; // 如果+号两侧都是整型，那么+代表 数字相加
//        System.out.println(k);
//
//        int a = 5;
//        String b = "5";
//        String c = a+b; // 如果+号两侧，任意一个是字符串，那么+代表字符串连接
//        System.out.println(c);
//
//
//        /**
//         * 观察类的多态现象
//         */
//        // 多态: 都是同一个类型，调用同一个方法，却能呈现不同的状态
//        // i1 和 i2 都是Item类型，都调用effect方法，输出不同的结果
//        Item i1= new LifePotion();
//        Item i2 = new MagicPotion();
//        System.out.print("i1 是Item类型，执行effect打印:");
//        i1.effect(); // 血瓶使用后，可以回血
//        System.out.print("i2也是Item类型，执行effect打印:");
//        i2.effect(); // 蓝瓶使用后，可以回魔法
//
//
//        /**
//         * 类的多态条件
//         */
//        // 要实现类的多态，需要如下条件
//        // 1. 父类（接口）引用指向子类对象
//        // 2. 调用的方法有重写
//        // 那么多态有什么作用呢？ 通过比较不使用多态与使用多态来进一步了解
//
//
//        /**
//         * 类的多态-不使用多态
//         */
//        public class Hero {
//            public String name;
//            protected float hp;
//
//            // 如果不使用多态，
//            // 假设英雄要使用血瓶和魔瓶，就需要为Hero设计两个方法 useLifePotion 、 useMagicPotion
//            // 除了血瓶和魔瓶还有很多种物品，那么就需要设计很多很多个方法， 比如 usePurityPotion 净化药水 、 useGuard 守卫 、 useInvisiblePotion 使用隐形药水 等等等等
//            public void useLifePotion(LifePotion lp){
//                lp.effect();
//            }
//            public void useMagicPotion(MagicPotion mp){
//                mp.effect();
//            }
//            public static void main(String[] args) {
//                Hero garen =  new Hero();
//                garen.name = "盖伦";
//                LifePotion lp =new LifePotion();
//                MagicPotion mp =new MagicPotion();
//                garen.useLifePotion(lp);
//                garen.useMagicPotion(mp);
//            }
//        }
//
//
//        /**
//         * 类的多态-使用多态
//         */
//        public class Hero {
//            public String name;
//            protected float hp;
//
//            // 如果物品的种类特别多，那么就需要设计很多的方法， 比如useArmor,useWeapon等等
//            // 这个时候采用多态来解决这个问题
//            // 设计一个方法叫做useItem，其参数类型是Item
//            //  如果是使用血瓶，调用该方法
//            //  如果是使用魔瓶，还是调用该方法
//            // 无论英雄要使用什么样的物品，只需要一个方法即可
//            public void useItem(Item i){
//                i.effect();
//            }
//            public static void main(String[] args) {
//                Hero garen =  new Hero();
//                garen.name = "盖伦";
//                LifePotion lp =new LifePotion();
//                MagicPotion mp =new MagicPotion();
//                garen.useItem(lp);
//                garen.useItem(mp);
//            }
//        }
//    }
//
//
//    /**
//     * 接口与继承 隐藏
//     */
//    void Hide() {
//        // 与重写类似，方法的重写是子类覆盖父类的对象方法
//        // 隐藏，就是子类覆盖父类的类方法
//
//        /**
//         * 父类
//         */
//        public class Hero {
//            public String name;
//            protected float hp;
//            //类方法，静态方法
//            //通过类就可以直接调用
//            public static void battleWin(){
//                System.out.println("hero battle win");
//            }
//        }
//
//        /**
//         * 子类隐藏父类的类方法
//         */
//        public class ADHero extends Hero implements AD{
//            @Override
//            public void physicAttack() {
//                System.out.println("进行物理攻击");
//            }
//            //隐藏父类的battleWin方法
//            public static void battleWin(){
//                System.out.println("ad hero battle win");
//            }
//            public static void main(String[] args) {
//                Hero.battleWin();
//                ADHero.battleWin();
//            }
//        }
//    }
//
//
//    /**
//     * 接口与继承 super
//     */
//    void Super() {
//        /**
//         * 准备一个显式提供无参构造方法的父类
//         */
//        public class Hero {
//            String name; //姓名
//            float hp; //血量
//            float armor; //护甲
//            int moveSpeed; //移动速度
//            public void useItem(Item i){
//                System.out.println("hero use item");
//                i.effect();
//            }
//            /**
//             * 父类显式提供两个构造方法
//             */
//            public Hero(String name){
//                System.out.println("Hero的有一个参数的构造方法 ");
//                this.name = name;
//            }
//            public Hero(){
//                System.out.println("Hero的构造方法 ");
//            }
//            public static void main(String[] args) {
//                new Hero(); // 在实例化Hero对象的时候，其构造方法会打印 “Hero的构造方法 "
//            }
//        }
//
//        /**
//         * 实例化子类，父类的构造方法一定会被调用
//         */
//        public class ADHero extends Hero implements AD{
//            int moveSpeed=400; //移动速度
//            @Override
//            public void physicAttack() {
//                System.out.println("进行物理攻击");
//            }
//            public int getMoveSpeed(){
//                // ADHero也提供了属性moveSpeed
//                return this.moveSpeed;
//            }
//            public int getMoveSpeed2(){
//                // 通过super调用父类的moveSpeed属性
//                return super.moveSpeed;
//            }
//            /**
//             * 子类显式调用父类带参构造方法
//             */
//            public ADHero(String name){
//                // 使用关键字super 显式调用父类带参的构造方法
//                super(name);
//                System.out.println("AD Hero的构造方法");
//            }
//            public ADHero(){
//                System.out.println("AD Hero的构造方法");
//            }
//
//            /**
//             * 调用父类方法
//             */
//            public void useItem(Item i) {
//                // 重写 useItem，并在其中通过super调用父类的useItem方法
//                System.out.println("adhero use item");
//                super.useItem(i);
//            }
//            public static void main(String[] args) {
//                // 实例化一个ADHero(), 其构造方法会被调用
//                // 其父类的构造方法也会被调用， 并且是父类构造方法先调用
//                // 子类构造方法会默认调用父类的 无参的构造方法
//                new ADHero();
//
//                // 子类显式调用父类带参构造方法
//                new ADHero("德莱文");
//
//                /**
//                 * 调用父类属性
//                 */
//                ADHero h = new ADHero();
//                System.out.println(h.getMoveSpeed());
//                System.out.println(h.getMoveSpeed2());
//            }
//        }
//    }
//
//
//    /**
//     * 接口与继承 Object类
//     */
//    void Object() {
//        /**
//         * Object类是所有类的父类
//         */
//        // 声明一个类的时候，默认是继承了Object
//        // public class Hero extends Object
//
//
//        /**
//         * toString()  即返回当前对象的字符串表达
//         *      通过 System.out.println 打印对象就是打印该对象的toString()返回值
//         */
//        void _toString() {
//            Heros h = new Heros();
//            h.name = "盖伦";
//            System.out.println(h.toString());
//            //直接打印对象就是打印该对象的toString()返回值
//            System.out.println(h);
//        }
//
//
//        /**
//         * finalize()
//         *      当一个对象没有任何引用指向的时候，它就满足垃圾回收的条件
//         *      当它被垃圾回收的时候，它的finalize() 方法就会被调用。
//         *      finalize() 不是开发人员主动调用的方法，而是由虚拟机JVM调用的。
//         */
//        void _finalize() {
//            //只有一引用
//            Heros h;
//            for (int i = 0; i < 100000; i++) {
//                //不断生成新的对象
//                //每创建一个对象，前一个对象，就没有引用指向了
//                //那些对象，就满足垃圾回收的条件
//                //当，垃圾堆积的比较多的时候，就会触发垃圾回收
//                //一旦这个对象被回收，它的finalize()方法就会被调用
//                h = new Heros();
//            }
//        }
//
//
//        /**
//         * equals()  用于判断两个对象的内容是否相同
//         */
//        void _equals() {
//            // 假设，当两个英雄的hp相同的时候，我们就认为这两个英雄相同
//            public class Hero {
//                protected float hp;
//                public boolean equals(Object o){
//                    if(o instanceof Hero){
//                        Hero h = (Hero) o;
//                        return this.hp == h.hp;
//                    }
//                    return false;
//                }
//                public static void main(String[] args) {
//                    Hero h1= new Hero();
//                    h1.hp = 300;
//                    Hero h2= new Hero();
//                    h2.hp = 400;
//                    Hero h3= new Hero();
//                    h3.hp = 300;
//                    System.out.println(h1.equals(h2));
//                    System.out.println(h1.equals(h3));
//                    /**
//                     * 也可以用 == ，判断两个引用，是否指向了同一个对象
//                     */
//                    System.out.println(h1==h2);
//                    System.out.println(h1==h3);
//                }
//            }
//        }
//
//
//        /**
//         * hashCode()
//         */
//        // hashCode方法返回一个对象的哈希值。
//        // hashCode的意义，将放在后续 hashcode 原理章节讲解
//
//
//        /**
//         * 线程同步相关方法
//         */
//        // Object还提供线程同步相关方法
//        //      wait()
//        //      notify()
//        //      notifyAll()
//        // 这部分内容的理解需要建立在对线程安全有足够的理解的基础之上，所以会放在线程交互 的章节讲解
//
//
//        /**
//         * getClass()
//         */
//        // getClass()会返回一个对象的类对象，属于高级内容。
//        // 关于类对象的详细内容请参考反射机制。
//    }
//
//
//    /**
//     * 接口与继承 final
//     */
//    void Final() {
//        /**
//         * final修饰类
//         */
//        // 当Hero被修饰成final的时候，表示Hero不能够被继承， 其子类会出现编译错误。
//        public final class Hero extends Object {
//            String name; //姓名
//            float hp; //血量
//        }
//
//
//        /**
//         * final修饰方法
//         */
//        public class Hero extends Object {
//            String name; //姓名
//            float hp; //血量
//            float armor; //护甲
//            int moveSpeed; //移动速度
//            // Hero 的 useItem 方法被修饰成 final ，那么该方法在子类（ADHero）中，不能够被重写
//            public final void useItem(Item i){
//                System.out.println("hero use item");
//                i.effect();
//            }
//            public Hero(){
//                System.out.println("Hero的无参的构造方法 ");
//            }
//            public static void main(String[] args) {
//                new Hero();
//            }
//        }
//
//
//        /**
//         * final修饰基本类型变量
//         */
//        public class Hero extends Object {
//            String name; //姓名
//            float hp; //血量
//            float armor; //护甲
//            int moveSpeed; //移动速度
//            public static void main(String[] args) {
//                // final修饰基本类型变量，表示该变量只有一次赋值机会
//                final int hp;
//                hp = 5; // 此处进行了赋值，下面就不能再赋值了
//                hp = 6;
//            }
//        }
//
//
//        /**
//         * final修饰引用
//         */
//        public class Hero extends Object {
//            String name; //姓名
//            float hp; //血量
//            float armor; //护甲
//            int moveSpeed; //移动速度
//            public static void main(String[] args) {
//                // h引用被修饰成final，表示该引用只有1次指向对象的机会
//                final Hero h;
//                h = new Hero(); // 此处进行了指向， 下面再进行指向 就出现编译错误了
//                h = new Hero();
//                h.hp = 5; // 但是，依然通过h引用修改对象的属性值hp，因为hp并没有final修饰
//            }
//        }
//
//
//        /**
//         * 常量
//         */
//        public class Hero extends Object {
//            // 常量指的是可以公开，直接访问，不会变化的值
//            // 比如，物品栏的数量是6个
//            public static final int itemTotalNumber = 6;
//            String name; //姓名
//            float hp; //血量
//            float armor; //护甲
//            int moveSpeed; //移动速度
//        }
//    }
//
//
//    /**
//     * 接口与继承 抽象类
//     */
//    void AbstractClasses() {
//        // 在类中声明一个方法，这个方法没有实现体，是一个“空”方法
//        // 这样的方法就叫抽象方法，使用修饰符“abstract"
//        // 当一个类有抽象方法的时候，该类必须被声明为抽象类
//
//        /**
//         * 抽象类
//         */
//        // 为Hero增加一个抽象方法 attack，并且把Hero声明为abstract的。
//        // APHero,ADHero,ADAPHero是Hero的子类，继承了Hero的属性和方法。
//        // 但是各自的攻击手段是不一样的，所以继承Hero类后，这些子类就必须提供不一样的attack方法实现。
//        public abstract class Hero {
//            String name;
//            float hp;
//            float armor;
//            int moveSpeed;
//            public static void main(String[] args) {}
//            // 抽象方法attack
//            // Hero的子类会被要求实现attack方法
//            public abstract void attack();
//        }
//        public class ADHero extends Hero implements AD {
//            public void physicAttack() {
//                System.out.println("进行物理攻击");
//            }
//            @Override
//            public void attack() {
//                physicAttack();
//            }
//        }
//
//
//        /**
//         * 抽象类可以没有抽象方法
//         */
//        // Hero类可以在不提供抽象方法的前提下，声明为抽象类
//        // 一旦一个类被声明为抽象类，就不能够被直接实例化
//        public abstract class Hero {
//            String name;
//            float hp;
//            float armor;
//            int moveSpeed;
//            public static void main(String[] args) {
//                // 虽然没有抽象方法，但是一旦被声明为了抽象类，就不能够直接被实例化
//                Hero h = new Hero();
//            }
//        }
//
//
//        /**
//         * 抽象类和接口的区别
//         *      区别1：
//         *          子类只能继承一个抽象类，不能继承多个
//         *          子类可以实现多个接口
//         *      区别2：
//         *          抽象类可以定义
//         *              public,protected,package,private
//         *              静态和非静态属性
//         *              final和非final属性
//         *          但是接口中声明的属性，只能是
//         *              public
//         *              静态
//         *              final的
//         *          即便没有显式的声明
//         *  注: 抽象类和接口都可以有实体方法。 接口中的实体方法，叫做默认方法
//         */
//        public interface AP {
//            public static final int resistPhysic = 100;
//
//            // resistMagic 即便没有显式的声明为 public static final
//            // 但依然默认为 public static final
//            int resistMagic = 0;
//            public void magicAttack();
//        }
//    }
//
//
//    /**
//     * 接口与继承 内部类
//     */
//    void InnerClasses() {
//        /**
//         * 非静态内部类
//         */
//        // 非静态内部类可以直接在一个类里面定义
//        // 语法: new 外部类().new 内部类()
//        public class Hero {
//            private String name; // 姓名
//            float hp; // 血量
//            float armor; // 护甲
//            int moveSpeed; // 移动速度
//            // 非静态内部类 BattleScore “战斗成绩”
//            // 非静态内部类，只有一个外部类对象存在的时候，才有意义
//            // 战斗成绩只有在一个英雄对象存在的时候才有意义
//            class BattleScore {
//                int kill;
//                int die;
//                int assit;
//                public void legendary() {
//                    if (kill >= 8)
//                        System.out.println(name + "超神！");
//                    else
//                        System.out.println(name + "尚未超神！");
//                }
//            }
//            public static void main(String[] args) {
//                Hero garen = new Hero();
//                garen.name = "盖伦";
//                // 实例化内部类
//                // BattleScore对象只有在一个英雄对象存在的时候才有意义
//                // 所以其实例化必须建立在一个外部类对象的基础之上
//                BattleScore score = garen.new BattleScore();
//                score.kill = 9;
//                score.legendary();
//            }
//        }
//
//
//        /**
//         * 静态内部类
//         */
//        // 在一个类里面声明一个静态内部类， 不需要一个外部类的实例为基础，可以直接实例化
//        // 语法：new 外部类.静态内部类();
//        // 因为没有一个外部类的实例，所以在静态内部类里面不可以访问外部类的实例属性和方法
//        // 除了可以访问外部类的私有静态成员外，静态内部类和普通类没什么大的区别
//        public class Hero {
//            public String name;
//            protected float hp;
//            private static void battleWin(){
//                System.out.println("battle win");
//            }
//            // 敌方的水晶
//            static class EnemyCrystal{
//                int hp=5000;
//                //如果水晶的血量为0，则宣布胜利
//                public void checkIfVictory(){
//                    if(hp==0){
//                        Hero.battleWin();
//                        //静态内部类不能直接访问外部类的对象属性
//                        System.out.println(name + " win this game");
//                    }
//                }
//            }
//            public static void main(String[] args) {
//                // 实例化静态内部类
//                Hero.EnemyCrystal crystal = new Hero.EnemyCrystal();
//                crystal.checkIfVictory();
//            }
//        }
//
//
//        /**
//         * 匿名类
//         */
//        // 匿名类指的是在声明一个类的同时实例化它，使代码更加简洁精练
//        // 通常情况下，要使用一个接口或者抽象类，都必须创建一个子类
//        // 有的时候，为了快速使用，直接实例化一个抽象类，并“当场”实现其抽象方法。
//        // 既然实现了抽象方法，那么就是一个新的类，只是这个类，没有命名。  这样的类，叫做匿名类
//        public abstract class Hero {
//            String name; //姓名
//            float hp; //血量
//            float armor; //护甲
//            int moveSpeed; //移动速度
//            public abstract void attack();
//            public static void main(String[] args) {
//                ADHero adh = new ADHero();
//                //通过打印adh，可以看到adh这个对象属于ADHero类
//                adh.attack();
//                System.out.println(adh);
//                Hero h = new Hero(){
//                    //当场实现attack方法
//                    public void attack() {
//                        System.out.println("新的进攻手段");
//                    }
//                };
//                h.attack();
//                //通过打印h，可以看到h这个对象属于Hero$1这么一个系统自动分配的类名
//                System.out.println(h);
//            }
//        }
//
//
//        /**
//         * 本地类
//         */
//        // 本地类可以理解为有名字的匿名类
//        // 内部类与匿名类不一样的是，内部类必须声明在成员的位置，即与属性和方法平等的位置。
//        // 本地类和匿名类一样，直接声明在代码块里面，可以是主方法，for循环里等等地方
//        public abstract class Hero {
//            String name; //姓名
//            float hp; //血量
//            float armor; //护甲
//            int moveSpeed; //移动速度
//            public abstract void attack();
//            public static void main(String[] args) {
//                // 与匿名类的区别在于，本地类有了自定义的类名
//                class SomeHero extends Hero{
//                    public void attack() {
//                        System.out.println( name+ " 新的进攻手段");
//                    }
//                }
//                SomeHero h = new SomeHero();
//                h.name = "地卜师";
//                h.attack();
//            }
//        }
//
//
//        /**
//         * 在匿名类中使用外部的局部变量
//         */
//        // 在匿名类中使用外部的局部变量，外部的局部变量必须修饰为final
//        // 为什么要声明为final，其机制比较复杂，请参考第二个Hero代码中的解释
//        // 注：在jdk8中，已经不需要强制修饰成final了，如果没有写final，不会报错，因为编译器偷偷的帮你加上了看不见的final
//        public abstract class Hero {
//
//            public abstract void attack();
//
//            public static void main(String[] args) {
//                //在匿名类中使用外部的局部变量damage 必须修饰为final
//                int damage = 5;
//
//                //这里使用本地类AnonymousHero来模拟匿名类的隐藏属性机制
//                //事实上的匿名类，会在匿名类里声明一个damage属性，并且使用构造方法初始化该属性的值
//                //在attack中使用的damage，真正使用的是这个内部damage，而非外部damage
//                //假设外部属性不需要声明为final
//                //那么在attack中修改damage的值，就会被暗示为修改了外部变量damage的值
//                //但是他们俩是不同的变量，是不可能修改外部变量damage的
//                //所以为了避免产生误导，外部的damage必须声明为final,"看上去"就不能修改了
//                class AnonymousHero extends Hero{
//                    int damage;
//                    public AnonymousHero(int damage){
//                        this.damage = damage;
//                    }
//                    public void attack() {
//                        damage = 10;
//                        System.out.printf("新的进攻手段，造成%d点伤害",this.damage );
//                    }
//                }
//                Hero h = new AnonymousHero(damage);
//            }
//        }
//    }
//
//
//    /**
//     * 接口与继承 默认方法
//     */
//    void DefaultMethod() {
//        /**
//         * 什么是默认方法
//         */
//        // 默认方法是JDK8新特性，指的是接口也可以提供具体方法了，而不像以前，只能提供抽象方法
//        public interface Mortal {
//            public void die();
//
//            // Mortal 这个接口，增加了一个默认方法 revive，这个方法有实现体，并且被声明为了default
//            default public void revive() {
//                System.out.println("本英雄复活了");
//            }
//        }
//
//
//        /**
//         * 为什么会有默认方法
//         */
//        // 假设没有默认方法这种机制，那么如果要为Mortal增加一个新的方法revive,那么所有实现了Mortal接口的类，都需要做改动。
//        // 但是引入了默认方法后，原来的类，不需要做任何改动，并且还能得到这个默认方法
//        // 通过这种手段，就能够很好的扩展新的类，并且做到不影响原来的类
//    }
//
//}
